package org.fududu.oauth2;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

/**
 * OAuth2.0 grant types enumeration.
 *
 * @author Fuchun
 * @since 1.0
 */
public enum GrantType {

    /**
     * Authorization Code grant
     */
    AUTHORIZATION_CODE("authorization_code", "oauth2.authorization_code", "Authorization Code"),

    /**
     * Implicit grant. Not contains {@code grant_type} parameter.
     */
    IMPLICIT("", "oauth2.implicit", "Implicit"),

    /**
     * Resource Owner Password Credentials Grant
     */
    RESOURCE_OWNER_PASSWORD("password", "oauth2.resource_owner_password",
            "Resource Owner Password Credentials Grant"),

    /**
     * Client Credentials Grant
     */
    CLIENT_CREDENTIALS("client_credentials", "oauth2.client_credentials", "Client Credentials Grant")

    ;

    final String value;
    /* i18n message code */
    final String code;
    /* default message text. */
    final String defaultText;

    GrantType(String value, String code, String defaultText) {
        this.value = value;
        this.code = code;
        this.defaultText = defaultText;
    }

    /**
     * Return this enum value.
     */
    public String getValue() {
        return value;
    }

    /**
     * Return this enum i18n message code.
     */
    public String getCode() {
        return code;
    }

    /**
     * Return this enum value default text message.
     */
    public String getDefaultText() {
        return defaultText;
    }

    /**
     * Return the {@code GrantType} of the specified grant type {@code value},
     * Default {@link #AUTHORIZATION_CODE} if the {@code value} none found.
     *
     * @param value the grant type value.
     * @return a {@code GrantType} instance of the specified {@code value}.
     */
    @NotNull
    public static GrantType of(String value) {
        return of(value, AUTHORIZATION_CODE);
    }

    @Contract("_, !null -> !null")
    public static GrantType of(String value, GrantType def) {
        if (value == null) {
            return def;
        }
        for (GrantType grantType : values()) {
            if (value.equals(grantType.value)) {
                return grantType;
            }
        }
        return def;
    }
}
